namespace Guia.Elements
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Windows.Automation;
    using Guia.Core;
    using Guia.Locator;

    /// <summary>
    /// This class represents a ToolBar.
    /// </summary>
    public class ToolBar : UiElement
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ToolBar"/> class.
        /// </summary>
        /// <param name="automationElement">
        /// The automation element.
        /// </param>
        public ToolBar(AutomationElement automationElement) : base(automationElement)
        {
        }

        /// <summary>
        /// Gets the default-condition to find a control by its type.
        /// </summary>
        public static SearchCondition ControlTypeCondition
        {
            get { return SearchCondition.ByControlType(ControlType.ToolBar); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the ToolBar is expanded or not.
        /// </summary>
        public bool IsExpanded
        {
            get
            {
                return this.GetTogglePattern().Current.ToggleState == ToggleState.On;
            }

            set
            {
                if (value != this.IsExpanded)
                {
                    this.GetTogglePattern().Toggle();
                }
            }
        }

        /// <summary>
        /// Expands the ToolBar.
        /// </summary>
        public void Expand()
        {
            this.IsExpanded = true;
        }

        /// <summary>
        /// Collapses the ToolBar.
        /// </summary>
        public void Collapse()
        {
            this.IsExpanded = false;
        }

        /// <summary>
        /// Gets the ToolBar item with the given AutomationId.
        /// If the item can not be found the ToolBar is expanded and the search is executed again.
        /// Because of the implementation of the ToolBar, the "expanded" items are not direct subelements of the ToolBar but of the main window.
        /// Due to usability reasons, this is simulated here. Be aware of that.
        /// </summary>
        /// <param name="automationId">
        /// The desired automationId of the item.
        /// </param>
        /// <typeparam name="T">
        /// The desired type of the item.
        /// </typeparam>
        /// <returns>
        /// The item of the given type and the given automationId within this ToolBar.
        /// </returns>
        /// <exception cref="ElementNotFoundException">
        /// </exception>
        /// <exception cref="ArgumentNullException">This exception is thrown if automationId is null.</exception>
        public T GetItem<T>(string automationId) where T : UiElement
        {
            Contract.Requires<ArgumentNullException>(automationId != null);
            T item;
            try
            {
                item = this.Get<T>(automationId);
            }
            catch (ElementNotFoundException)
            {
                // if the ToolBar already is expanded, rethrow the Exception
                if (this.IsExpanded)
                {
                    throw;
                }
                
                // if not, expand it and search for the item
                this.Expand();
                IWindow parentWindow = this.ParentWindow;
                item = parentWindow.Get<T>(automationId);
            }

            if (item == null)
            {
                throw new ElementNotFoundException("Could not find any element with the AutomationId " + automationId);
            }

            return item;
        }

        /// <summary>
        /// Returns the TogglePattern of the underlying AutomationElement.
        /// </summary>
        /// <returns>
        /// The TogglePattern.
        /// </returns>
        private TogglePattern GetTogglePattern()
        {
            return this.Get<Button>("OverflowButton").GetPattern<TogglePattern>();
        }
    }
}